﻿/* Escala de todo el contenido de la página para la adaptación al tamaño del monitor / área visible (descontando el área de la barra de títulos y de las barras del navegador agregadas).
 * Manual / documentación / forma de uso: Escala.doc
 *
 * Bruma Rubí 15-sep-2009
 *
 *
 * versíon 2:
 * - Implementa la difusión de eventos
 * - Parametriza el tamaño mínimo de escalamiento
 * - Permite 2 modos diferentes de escalamiento: circunscrito e inscrito
 *
 * Bruma Rubí, 25-oct-2009
 */
 
import mx.events.EventDispatcher;
 
class EscalaDimension {
	public static var INSCRITO:Number = 1;
	public static var CIRCUNSCRITO:Number = 2;

	private var _visible_h, _visible_v, _min_h, _min_v, _width_ini, _height_ini:Number;
	private var _xscale_ini, _yscale_ini:Number;
	private var _tipo:Number;
	private var _obj_escalar:MovieClip;
	
	/* parám. obj_escalar: el MovieClip sobre el cual aplicar el escalamiento
	 *
	 * parám. visible_h, visible_v: ancho y alto con respecto a los cuales:
	 * 1. Cuando el ancho o el alto del escenario respectivamente está por debajo de esos valores provoca el escalamiento hacia abajo del MovieClip
	 * 2. Cuando el ancho o el alto del escenario respectivamente iguala o supera los valores el MovieClip no se escala / recupera su escala dada en la colocación del objeto (entorno de diseño por ejemplo). (Código de referencia: "A1")
	 * El significado más bien es: visible obligatorio (ese ancho o alto se tiene que ver siempre, aunque implique escalamiento)
	 *
	 * parám. tipo: alguno de los valores:
	 * - EscalaDimension.INSCRITO: tal como se usan los términos circunscrito e inscrito en la bibliografía sobre integral definida (ver: Cálculo Diferencial e Integral de Piskunov)
	 * - EscalaDimension.CIRCUNSCRITO: tal como se usan los términos circunscrito e inscrito en la bibliografía sobre integral definida (ver: Cálculo Diferencial e Integral de Piskunov)
	 * - otros propuestos a futuro (en caso de ser necesario): EscalaDimension.SOLO_ANCHO, EscalaDimension.SOLO_ALTO: escala 1 de las 2 dimensiones y la otra no
	 *   (esto se emula perfectamente con las variable min_h o min_v igualándolas a visible_h o visible_v respectivamente, o bien igualando visible_h o visible_v a 0)
	 * - EscalaDimension.INDEPENDIENTES: el ancho y el alto se escalan independientemente / ajuste absoluto
	 *
	 * parám. min_h, min_v: cuando el escenario toma ancho o alto inferios a estos valores, se deja de aplicar escalamiento. Queda en el tamaño escalado hasta min_h y min_v. El valor 0 no es un caso especial.
	 * funcionan como la proyección escalada de visible_h y visible_h, no como la de obj_escalar._width ni obj_escalar._height
	 * Es decir: la cantidad de pixels representados por min_h / min_v es la misma que la de visible_h / visible_v del obj_escalar en su tamaño original
	 *
	 * Escalas:
	 * Sistema de referencia 1 = {obj_escalar._width, obj_escalar._height, Stage.width, Stage.height}
	 * Sistema de referencia 2 = {min_h, min_v, obj_escalar._width (inicial), obj_escalar._height (inicial), visible_h, visible_v}
	 *
	 * (sistema de referencia con el significado que se le da en Física, ej.: principio de relatividad de Galileo Galilei)
	 */
	function EscalaDimension(obj_escalar:MovieClip, visible_h:Number, visible_v:Number, tipo:Number, min_h:Number, min_v:Number) {
		EventDispatcher.initialize(this);
	
		/* Le sacamos la responsabilidad del escalamiento al reproductor de Flash, para
		 * tenerla bajo el control de este módulo
		 */
		Stage.scaleMode = "noScale";
		/* En navegadores como ser Internet Explorer esto no sería necesario.
		 * En navegadores como ser Firefox 2.x sí porque alineaciones <> "TL"
		 * en gral. => el redimensionamiento de la ventana del usuario no es notificada
		 * al objeto Stage
		 */
		Stage.align = "TL";

		_obj_escalar = obj_escalar;
		_visible_h = visible_h;
		_visible_v = visible_v;
		_min_h = min_h;
		_min_v = min_v;
		//_width_ini = obj_escalar._width;
		//_height_ini = obj_escalar._height;
		_xscale_ini = obj_escalar._xscale;
		_yscale_ini = obj_escalar._yscale;
		_tipo = tipo;
		
		Stage.addListener(this);
	}
	
	function onResize() {
		escalar();
	}
	
	public function escalar() {
		trace("EscalaDimension.escalar: " + _obj_escalar + ", " + Stage.width + ", " + Stage.height + ", " + _min_h + ", " + _min_v + ", " + _visible_h + ", " + _visible_v + ", " + _width_ini + ", " + _height_ini + ", " + _xscale_ini + ", " + _yscale_ini + ", " + dispatchEvent);
		/* aserciones:
		 * _min_h <= _visible_h
		 * _min_v <= _visible_v
		 * _visible_{h|v}!=0
		 *
		 * Se admiten anchos / altos del escenario en el rango de [_min_h._visible_h]/[_min_v._visible_v] respectivamente
		 */
		var stage_w:Number = Math.max(_min_h, Math.min(_visible_h, Stage.width));
		var stage_h:Number = Math.max(_min_v, Math.min(_visible_v, Stage.height));
		
		var prop_h:Number = stage_w/_visible_h;
		var prop_v:Number = stage_h/_visible_v;
		
		var prop:Number = _tipo==INSCRITO ? Math.min(prop_h, prop_v) : Math.max(prop_h, prop_v);
		
		//trace("ajuste: " + Stage.width + ", " + Stage.height + ", " + STAGE_W_DIS + ", " + STAGE_H_DIS + ", " + prop_h + ", " + prop_w);
		_obj_escalar._xscale = _xscale_ini * prop;
		_obj_escalar._yscale = _yscale_ini * prop;
		/* Dentro de _obj_escalar podría haber un objeto listener del Stage propio que invoque a la función
		 * ajuste del propio _obj_escalar, pero es necesario que primero se ejecute el código de esta versión
		 * de la función ajuste, porque la otra depende de la finalización de esta.
		 * Por eso se lo acopla secuencialmente. Si cada una fuera invocada por su propio listener de Stage
		 * no estaría determinado cuál se ejecuta primero.
		 */
		dispatchEvent({type: "resize", target: this, obj_escalar: _obj_escalar});	
	}
	
	// Inicializada por EventDispatcher
	function addEventListener(/*...*/) {
	}
	
	function dispatchEvent(/*...*/) {
	}
	
	function removeEventListener(/*...*/) {
	}
}